Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

perf($compile): remove use of deepEquals and $stateful interceptor from bidi bindings #16550

Closed
wants to merge 1 commit into from

Conversation

jbedard
Copy link
Collaborator

@jbedard jbedard commented May 4, 2018

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
performance, bug fixes (the two my-component reference tests previously failed)

What is the current behavior? (You can also link to an open issue here)

  • Bidirection inputs use a $stateful interceptor. This means the full expression is executed on every digest due to no input-watching.
  • Bidirection inputs use deep equals on literal objects, to workaround the $stateful interceptor

What is the new behavior (if this is a feature change)?
No more $stateful interceptors or deep watching when using bidi directive/component inputs.

Does this PR introduce a breaking change?
Maybe? But no tests required changing (other then the watcher counts). I thought removing the use of deep equals on literals might change something but I'm not 100% sure...

I guess it might reduce the number of times a literal is evaluated and therefore copy a new instance into the destination less frequently. If someone was modifying the internals of the object, those modifications will now be overridden less often? Or maybe previously they would get a noassign error because the deepEquals detected that change, and now the simpleCompare won't detect it at all...

…om bidi bindings

Previously bidirectional bindings were implemented using a custom watch
interceptor which stored the component/directive inner value and therefore
had to be marked as `$stateful`. The use of a `$stateful` interceptor
prevented some optimizations from being used.

As a result of using a `$stateful` interceptor the bindings would be
executed on each and every digest. For literal expressions this would
recreate the literal every digest and therefore require `objectEquality
= true`, causing a `angular.equals` call on every digest.
@jbedard
Copy link
Collaborator Author

jbedard commented May 4, 2018

I've added a few more tests, including one that failed before the PR (should copy parent changes, even if deep equal to old). Also added more info to the commit message.

So far I have failed to find any cases that fail only after the change, but I'm still assuming there are some edge cases that this might "break" so I'd love to get this in before 1.7.

parentSet = parentGet.assign || function() {
// reset the change, or we will throw this exception on every $digest
lastValue = destination[scopeName] = parentGet(scope);
throw $compileMinErr('nonassign',
'Expression \'{0}\' in attribute \'{1}\' used with directive \'{2}\' is non-assignable!',
attrs[attrName], attrName, directive.name);
};
var childGet = function childGet() { return destination[scopeName]; };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the AngularJS coding style to put the var declarations at the top of the function?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think normally, but not 2 lines below this 🤷‍♂️ Preference?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😨

@jbedard
Copy link
Collaborator Author

jbedard commented May 9, 2018

Decided not to do this. Too risky at this stage.

@jbedard jbedard closed this May 9, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants